home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / ax25cmd.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  23KB  |  1,067 lines

  1. /* AX25 control commands
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  * 
  4.  * Mods by G1EMM
  5.  * Mods by PA0GRI
  6.  * Mods by N1BEE
  7.  */
  8. /*
  9. ** FILE: ax25cmd.c
  10. **
  11. ** AX.25 command handler.
  12. **
  13. ** 09/24/90 Bob Applegate, wa2zzx
  14. **    Added BCTEXT, BC, and BCINTERVAL commands for broadcasting an id
  15. **    string using UI frames.
  16. **
  17. ** 27/09/91 Mike Bilow, N1BEE
  18. **    Added Filter command for axheard control
  19. */
  20.  
  21. #include <stdio.h>
  22. #ifdef MSDOS
  23. #include <dos.h>
  24. #endif
  25. #include "global.h"
  26. #include "config.h"
  27. #include "mbuf.h"
  28. #include "timer.h"
  29. #include "proc.h"
  30. #include "iface.h"
  31. #include "ax25.h"
  32. #include "lapb.h"
  33. #include "cmdparse.h"
  34. #include "socket.h"
  35. #include "mailbox.h"
  36. #include "session.h"
  37. #include "tty.h"
  38. #include "nr4.h"
  39. #include "commands.h"
  40. #include "pktdrvr.h"
  41. #include "netrom.h" 
  42.  
  43. int axheard __ARGS((struct iface *ifp));
  44. static void axflush __ARGS((struct iface *ifp));
  45. static int doaxfilter __ARGS((int argc,char *argv[],void *p));
  46. static int doaxflush __ARGS((int argc,char *argv[],void *p));
  47. static int doaxirtt __ARGS((int argc,char *argv[],void *p));
  48. static int doaxkick __ARGS((int argc,char *argv[],void *p));
  49. static int doaxreset __ARGS((int argc,char *argv[],void *p));
  50. static int doaxroute __ARGS((int argc,char *argv[],void *p));
  51. static int doaxstat __ARGS((int argc,char *argv[],void *p));
  52. static int doaxwindow __ARGS((int argc,char *argv[],void *p));
  53. static int dobc __ARGS((int argc,char *argv[],void *p));
  54. static int dobcint __ARGS((int argc,char *argv[],void *p));
  55. static int dobcport __ARGS((int argc,char *argv[],void *p));
  56. static int dobctext __ARGS((int argc,char *argv[],void *p));
  57. static int doaxhport __ARGS((int argc,char *argv[],void *p));
  58. static int doaxhsize __ARGS((int argc,char *argv[],void *p));
  59. static int doblimit __ARGS((int argc,char *argv[],void *p));
  60. static int dodigipeat __ARGS((int argc,char *argv[],void *p));
  61. static int domaxframe __ARGS((int argc,char *argv[],void *p));
  62. static int domycall __ARGS((int argc,char *argv[],void *p));
  63. static int don2 __ARGS((int argc,char *argv[],void *p));
  64. static int dopaclen __ARGS((int argc,char *argv[],void *p));
  65. static int dopthresh __ARGS((int argc,char *argv[],void *p));
  66. static int dot3 __ARGS((int argc,char *argv[],void *p));
  67. static int doaxtype __ARGS((int argc,char *argv[],void *p));
  68. static int dot4 __ARGS((int argc,char *argv[],void *p));
  69. static int doversion __ARGS((int argc,char *argv[],void *p));
  70. int donralias __ARGS((int argc,char *argv[],void *p));
  71. #ifdef AXBCSTR
  72. static void ax_bc __ARGS((struct iface *axif, char *str));
  73. #else
  74. static void ax_bc __ARGS((struct iface *axif));
  75. #endif
  76. static int axdest __ARGS((struct iface *ifp));
  77. #ifdef TTYCALL
  78. static int dottycall __ARGS((int argc, char *argv[], void *p));
  79. #endif
  80.  
  81. extern char Myalias[AXALEN];    /* the NETROM alias in 'call' form */
  82. extern char Nralias[ALEN+1];      /* the NETROM alias in 'alias' form */
  83. #ifdef TTYCALL
  84. extern char Ttycall[AXALEN];    /* the ttylink call in 'call' form */
  85. #endif
  86. extern int axheard_filter_flag;     /* in axheard.c */
  87. /* Defaults for IDing. */
  88. char *axbctext = NULL;                          /* Text to send */
  89. static struct timer Broadtimer; /* timer for broadcasts */
  90.  
  91. char *Ax25states[] = {
  92.     "",
  93.     "Disconnected",
  94.     "Listening",
  95.     "Conn pending",
  96.     "Disc pending",
  97.     "Connected",
  98.     "Recovery",
  99. };
  100.  
  101. /* Ascii explanations for the disconnect reasons listed in lapb.h under
  102.  * "reason" in ax25_cb
  103.  */
  104. char *Axreasons[] = {
  105.     "Normal",
  106.     "DM received",
  107.     "Timeout"
  108. };
  109.  
  110. static struct cmds Axcmds[] = {
  111.     "alias",    donralias,  0, 0, NULLCHAR,
  112.     "bc",       dobc,       0, 0, NULLCHAR,
  113.     "bcinterval",dobcint,   0, 0, NULLCHAR,
  114.     "bcport",   dobcport,   0, 0, NULLCHAR,
  115.     "blimit",       doblimit,       0, 0, NULLCHAR,
  116.     "bctext",       dobctext,       0, 0, NULLCHAR,
  117.     "dest",     doaxdest,   0, 0, NULLCHAR,
  118.     "digipeat", dodigipeat, 0, 0, NULLCHAR,
  119.     "filter",       doaxfilter,     0, 0, NULLCHAR,
  120.     "flush",        doaxflush,      0, 0, NULLCHAR,
  121.     "heard",        doaxheard,      0, 0, NULLCHAR,
  122.     "hearddest",    doaxdest,       0, 0, NULLCHAR,
  123.     "hport",    doaxhport,  0, 0, NULLCHAR,
  124.     "hsize",    doaxhsize,  0, 0, NULLCHAR,
  125.     "irtt",     doaxirtt,   0, 0, NULLCHAR,
  126.     "kick",         doaxkick,       0, 2, "ax25 kick <axcb>",
  127.     "maxframe",     domaxframe,     0, 0, NULLCHAR,
  128.     "mycall",       domycall,       0, 0, NULLCHAR,
  129.     "paclen",       dopaclen,       0, 0, NULLCHAR,
  130.     "pthresh",      dopthresh,      0, 0, NULLCHAR,
  131.     "reset",        doaxreset,      0, 2, "ax25 reset <axcb>",
  132.     "retry",        don2,           0, 0, NULLCHAR,
  133.     "route",        doaxroute,      0, 0, NULLCHAR,
  134.     "status",       doaxstat,       0, 0, NULLCHAR,
  135.     "t3",           dot3,           0, 0, NULLCHAR,
  136.     "t4",           dot4,           0, 0, NULLCHAR,
  137.     "timertype",    doaxtype,       0, 0, NULLCHAR,
  138. #ifdef TTYCALL
  139.     "ttycall",    dottycall,    0, 0, NULLCHAR,
  140. #endif
  141.     "version",      doversion,      0, 0, NULLCHAR,
  142.     "window",       doaxwindow,     0, 0, NULLCHAR,
  143.     NULLCHAR,
  144. };
  145.  
  146. /* Multiplexer for top-level ax25 command */
  147. int
  148. doax25(argc,argv,p)
  149. int argc;
  150. char *argv[];
  151. void *p;
  152. {
  153.     return subcmd(Axcmds,argc,argv,p);
  154. }
  155.  
  156. /* define the system's alias callsign ,
  157.  * if netrom is used, this is also the netrom alias ! - WG7J
  158.  */
  159.  
  160. #ifdef MAILBOX
  161. #include "mailbox.h"
  162. #endif
  163.  
  164. int
  165. donralias(argc,argv,p)
  166. int argc ;
  167. char *argv[] ;
  168. void *p;
  169. {
  170.     char tmp[AXBUF];
  171.  
  172.     if(argc < 2) {
  173.     tprintf("%s\n",pax25(tmp,Myalias));
  174.     return 0;
  175.     }
  176.     if( (setcall(Myalias,argv[1]) == -1)
  177. #ifdef NETROM
  178.        || (putalias(Nralias,argv[1],1) == -1)
  179. #endif
  180.                          ){
  181.         tputs("can't set alias\n");
  182.         Myalias[0] = '\0';
  183. #ifdef NETROM
  184.         Nralias[0] = '\0';
  185. #endif
  186.         return 0;
  187.     }
  188. #ifdef MAILBOX
  189.     setmbnrid();
  190. #endif
  191.     return 0;
  192. }
  193.  
  194. /*
  195. ** This function is called to send the current broadcast message
  196. ** and reset the timer.
  197. */
  198.  
  199. static int dobc(argc,argv,p)
  200. int argc;
  201. char *argv[];
  202. void *p;
  203. {
  204.     struct iface *ifa;
  205.  
  206.     if (argc < 2)
  207.     {
  208.         tprintf("you need to specify an interface\n");
  209.         return 1;
  210.     }
  211.  
  212.     ifa = Ifaces;
  213.     while (ifa != NULL && stricmp(ifa->name,argv[1]))
  214.         ifa = ifa->next;
  215.     if (ifa == NULL)
  216.         tprintf("unknown interface\n");
  217.     else if (ifa->type != CL_AX25)
  218.         tprintf("not an AX.25 interface\n");
  219. #ifdef AXBCSTR
  220.     else if (argc > 2)
  221.         ax_bc(ifa, argv[2]);
  222. #endif
  223.     else
  224.     {
  225. #ifdef AXBCSTR
  226.         ax_bc(ifa, axbctext);
  227. #else
  228.         ax_bc(ifa);
  229. #endif
  230.         stop_timer(&Broadtimer) ;       /* in case it's already running */
  231.         start_timer(&Broadtimer);               /* and fire it up */
  232.     }
  233.     return 0;
  234. }
  235.  
  236.  
  237.  
  238. /*
  239. ** View/Change the message we broadcast.
  240. */
  241.  
  242. static int dobctext(argc,argv,p)
  243. int argc;
  244. char *argv[];
  245. void *p;
  246. {
  247.     if (argc < 2)
  248.         tprintf("Broadcast text: %s\n",axbctext);
  249.     else
  250.     {
  251.         if (axbctext != NULL) free(axbctext);
  252.         axbctext = malloc(strlen(argv[1]) + 1);    /* KF8NH: +1 pls... */
  253.         strcpy(axbctext,argv[1]);
  254.     }
  255.     return 0;
  256. }
  257.  
  258.  
  259.  
  260. #define TICKSPERSEC     (1000L / MSPTICK)       /* Ticks per second */
  261.  
  262. /*
  263. ** Examine/change the broadcast interval.
  264. */
  265.  
  266. static int dobcint(argc,argv,p)
  267. int argc;
  268. char *argv[];
  269. void *p;
  270. {
  271.     void dobroadtick __ARGS((void));
  272.  
  273.     if(argc < 2)
  274.     {
  275.         tprintf("Broadcast timer %lu/%lu seconds\n",
  276.             read_timer(&Broadtimer)/1000L,
  277.             dur_timer(&Broadtimer)/1000L);
  278.         return 0;
  279.     }
  280.     stop_timer(&Broadtimer) ;       /* in case it's already running */
  281.     Broadtimer.func = (void (*)__ARGS((void*)))dobroadtick;/* what to call on timeout */
  282.     Broadtimer.arg = NULLCHAR;              /* dummy value */
  283.     set_timer(&Broadtimer,atoi(argv[1])*1000L);     /* set timer duration */
  284.     start_timer(&Broadtimer);               /* and fire it up */
  285.     return 0;
  286. }
  287.  
  288. /* Configure a port to do ax.25 beacon broadcasting */
  289. static int
  290. dobcport(argc,argv,p)
  291. int argc;
  292. char *argv[];
  293. void *p;
  294. {
  295.     return setflag(argc,argv[1],AX25_BEACON,argv[2]);
  296. }
  297.  
  298. int Maxax25heard;
  299.  
  300. /* Set the size of the ax.25 heard list */
  301. int doaxhsize(int argc,char *argv[],void *p) {
  302.     return setint(&Maxax25heard,"Max ax-heard",argc,argv);
  303. }
  304.  
  305. /* Configure a port to do ax.25 heard logging */
  306. static int
  307. doaxhport(argc,argv,p)
  308. int argc;
  309. char *argv[];
  310. void *p;
  311. {
  312.     return setflag(argc,argv[1],LOG_AXHEARD,argv[2]);
  313. }
  314.  
  315. void
  316. #ifdef PROTOTYPES
  317. dobroadtick(void)
  318. #else
  319. dobroadtick()
  320. #endif
  321. {
  322.     struct iface *ifa;
  323.  
  324.     ifa = Ifaces;
  325.  
  326.     while (ifa != NULL)
  327.     {
  328.     if (ifa->flags & AX25_BEACON)
  329. #ifdef AXBCSTR
  330.         ax_bc(ifa, axbctext);
  331. #else
  332.         ax_bc(ifa);
  333. #endif
  334.         ifa = ifa->next;
  335.     }
  336.  
  337.     /* Restart timer */
  338.     start_timer(&Broadtimer) ;
  339. }
  340.  
  341.  
  342.  
  343. /*
  344. ** This is the low-level broadcast function.
  345. */
  346.  
  347. #ifdef AXBCSTR
  348. static void ax_bc(axif, axbctext)
  349. char *axbctext;
  350. #else
  351. static void ax_bc(axif)
  352. #endif
  353. struct iface *axif;
  354. {
  355.     struct mbuf *hbp;
  356.     int i;
  357.     
  358.     /* prepare the header */
  359.     i = strlen(axbctext);
  360.     if((hbp = alloc_mbuf(i)) == NULLBUF)
  361.         return;
  362.         
  363.     hbp->cnt = i;   
  364.     memcpy(hbp->data,axbctext,(size_t)i);
  365.  
  366.     (*axif->output)(axif, Ax25multi[IDCALL], axif->hwaddr,
  367.         PID_NO_L3, hbp);        /* send it */
  368.  
  369.     /*
  370.     ** Call another function to reset the timer...
  371.     reset_bc_timer();
  372.     */
  373. }
  374.  
  375.  
  376. int
  377. doaxheard(argc,argv,p)
  378. int argc;
  379. char *argv[];
  380. void *p;
  381. {
  382.     struct iface *ifp;
  383.  
  384.     if(argc > 1){
  385.         if((ifp = if_lookup(argv[1])) == NULLIF){
  386.         tprintf(Badinterface,argv[1]);
  387.             return 1;
  388.         }
  389.     if(ifp->type != CL_AX25){
  390.             tprintf("Interface %s not AX.25\n",argv[1]);
  391.             return 1;
  392.         }
  393.     if(ifp->flags & LOG_AXHEARD)
  394.         axheard(ifp);
  395.     else
  396.         tputs("not active\n");
  397.         return 0;
  398.     }
  399.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  400.     if(ifp->type != CL_AX25 || !(ifp->flags & LOG_AXHEARD))
  401.             continue;       /* Not an ax.25 interface */
  402.         if(axheard(ifp) == EOF)
  403.             break;
  404.     }
  405.     return 0;
  406. }
  407. int
  408. axheard(ifp)
  409. struct iface *ifp;
  410. {
  411.     int col = 0;
  412.     struct lq *lp;
  413.     char tmp[AXBUF];
  414.  
  415.     if(ifp->hwaddr == NULLCHAR)
  416.         return 0;
  417.  
  418.     tprintf("Interface  Station   Time since send  Pkts sent\n");
  419.     tprintf("%-9s  %-9s   %12s    %7lu\n",ifp->name,pax25(tmp,ifp->hwaddr),
  420.      tformat(secclock() - ifp->lastsent),ifp->rawsndcnt);
  421.  
  422.     tprintf("Station   Time since heard Pkts rcvd : ");
  423.     tprintf("Station   Time since heard Pkts rcvd\n");
  424.     for(lp = Lq;lp != NULLLQ;lp = lp->next){
  425.         if(lp->iface != ifp)
  426.             continue;
  427.         if(col)
  428.             tprintf("  : ");
  429.         if(tprintf("%-9s   %12s    %7lu",pax25(tmp,lp->addr),
  430.          tformat(secclock() - lp->time),lp->currxcnt) == EOF)
  431.             return EOF;
  432.         if(col){
  433.             if(tprintf("\n") == EOF){
  434.                 return EOF;
  435.             } else {
  436.                 col = 0;
  437.             }
  438.         } else {
  439.             col = 1;
  440.         }
  441.     }
  442.     if(col)
  443.         tprintf("\n");
  444.     return 0;
  445. }
  446. int
  447. doaxdest(argc,argv,p)
  448. int argc;
  449. char *argv[];
  450. void *p;
  451. {
  452.     struct iface *ifp;
  453.  
  454.     if(argc > 1){
  455.         if((ifp = if_lookup(argv[1])) == NULLIF){
  456.         tprintf(Badinterface,argv[1]);
  457.             return 1;
  458.         }
  459.         if(ifp->output != ax_output){
  460.             tprintf("Interface %s not AX.25\n",argv[1]);
  461.             return 1;
  462.         }
  463.         axdest(ifp);
  464.         return 0;
  465.     }
  466.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  467.         if(ifp->output != ax_output)
  468.             continue;       /* Not an ax.25 interface */
  469.         if(axdest(ifp) == EOF)
  470.             break;
  471.     }
  472.     return 0;
  473. }
  474. static int
  475. axdest(ifp)
  476. struct iface *ifp;
  477. {
  478.     struct ld *lp;
  479.     struct lq *lq;
  480.     char tmp[AXBUF];
  481.  
  482.     if(ifp->hwaddr == NULLCHAR)
  483.         return 0;
  484.     tprintf("%s:\n",ifp->name);
  485.     tprintf("Station   Last ref         Last heard           Pkts\n");
  486.     for(lp = Ld;lp != NULLLD;lp = lp->next){
  487.         if(lp->iface != ifp)
  488.             continue;
  489.  
  490.         tprintf("%-10s%-17s",
  491.          pax25(tmp,lp->addr),tformat(secclock() - lp->time));
  492.  
  493.         if(addreq(lp->addr,ifp->hwaddr)){
  494.             /* Special case; it's our address */
  495.             tprintf("%-17s",tformat(secclock() - ifp->lastsent));
  496.         } else if((lq = al_lookup(ifp,lp->addr,0)) == NULLLQ){
  497.             tprintf("%-17s","");
  498.         } else {
  499.             tprintf("%-17s",tformat(secclock() - lq->time));
  500.         }
  501.         if(tprintf("%8lu\n",lp->currxcnt) == EOF)
  502.             return EOF;
  503.     }
  504.     return 0;
  505. }
  506.  
  507. static int
  508. doaxfilter(argc,argv,p)
  509. int argc;
  510. char *argv[];
  511. void *p;
  512. {
  513.     if(argc >= 2){
  514.         setint(&axheard_filter_flag,"ax25 heard filter",argc,argv);
  515.     } else {
  516.         tprintf("Usage: ax25 filter <0|1|2|3>\n");
  517.         return 1;
  518.     }
  519.  
  520.     tprintf("Callsign loggin by source ");
  521.     if(axheard_filter_flag & AXHEARD_NOSRC)
  522.         tprintf("disabled, ");
  523.     else
  524.         tprintf("enabled, ");
  525.     tprintf("by destination ");
  526.     if(axheard_filter_flag & AXHEARD_NODST)
  527.         tprintf("disabled\n");
  528.     else
  529.         tprintf("enabled\n");
  530.     return 0;
  531. }
  532.  
  533. static int
  534. doaxflush(argc,argv,p)
  535. int argc;
  536. char *argv[];
  537. void *p;
  538. {
  539.     struct iface *ifp;
  540.  
  541.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  542.         if(ifp->output != ax_output)
  543.             continue;       /* Not an ax.25 interface */
  544.         axflush(ifp);
  545.     }
  546.     return 0;
  547. }
  548. static void
  549. axflush(ifp)
  550. struct iface *ifp;
  551. {
  552.     struct lq *lp,*lp1;
  553.     struct ld *ld,*ld1;
  554.  
  555.     ifp->rawsndcnt = 0;
  556.     for(lp = Lq;lp != NULLLQ;lp = lp1){
  557.         lp1 = lp->next;
  558.         free((char *)lp);
  559.     }
  560.     Lq = NULLLQ;
  561.     for(ld = Ld;ld != NULLLD;ld = ld1){
  562.         ld1 = ld->next;
  563.         free((char *)ld);
  564.     }
  565.     Ld = NULLLD;
  566. }
  567.  
  568. static int
  569. doaxreset(argc,argv,p)
  570. int argc;
  571. char *argv[];
  572. void *p;
  573. {
  574.     struct ax25_cb *axp;
  575.  
  576.     axp = MK_FP(htoi(argv[1]),8);
  577.     if(!ax25val(axp)){
  578.         tprintf(Notval);
  579.         return 1;
  580.     }
  581.     reset_ax25(axp);
  582.     return 0;
  583. }
  584.  
  585. /* Display AX.25 link level control blocks */
  586. static int
  587. doaxstat(argc,argv,p)
  588. int argc;
  589. char *argv[];
  590. void *p;
  591. {
  592.     register struct ax25_cb *axp;
  593.     char tmp[AXBUF];
  594.     char tmp2[AXBUF];
  595.  
  596.     if(argc < 2){
  597. #ifdef UNIX
  598.         tprintf("&AXB     Snd-Q   Rcv-Q   Remote    Local     Iface  State\n");
  599. #else
  600.     tprintf("&AXB Snd-Q   Rcv-Q   Remote    Local     Iface  State\n");
  601. #endif
  602.         for(axp = Ax25_cb;axp != NULLAX25; axp = axp->next){
  603. #ifdef UNIX
  604.             if(tprintf("%8.8lx %-8d%-8d%-10s%-10s%-7s%s\n",
  605. #else
  606.         if(tprintf("%4.4x %-8d%-8d%-10s%-10s%-7s%s\n",
  607. #endif
  608.         FP_SEG(axp),
  609.                 len_q(axp->txq),len_p(axp->rxq),
  610.                 pax25(tmp,axp->remote),
  611.         pax25(tmp2,axp->local),
  612.         axp->iface?axp->iface->name:"",
  613.                 Ax25states[axp->state]) == EOF)
  614.                     return 0;
  615.         }
  616.         return 0;
  617.     }
  618.     axp = MK_FP(htoi(argv[1]),8);
  619.     if(!ax25val(axp)){
  620.         tprintf(Notval);
  621.         return 1;
  622.     }
  623.     st_ax25(axp);
  624.     return 0;
  625. }
  626. /* Dump one control block */
  627. void
  628. st_ax25(axp)
  629. register struct ax25_cb *axp;
  630. {
  631.     char tmp[AXBUF];
  632.     char tmp2[AXBUF];
  633.  
  634.     if(axp == NULLAX25)
  635.         return;
  636. #ifdef UNIX
  637.     tprintf("&AXB     Local     Remote    Iface  RB V(S) V(R) Unack P Retry State\n");
  638.     tprintf("%8.8lx %-9s %-9s %-6s %c%c",FP_SEG(axp),
  639. #else
  640.     tprintf("&AXB Local     Remote    Iface  RB V(S) V(R) Unack P Retry State\n");
  641.     tprintf("%4.4x %-9s %-9s %-6s %c%c",FP_SEG(axp),
  642. #endif
  643.     pax25(tmp,axp->local),
  644.     pax25(tmp2,axp->remote),
  645.     axp->iface?axp->iface->name:"",
  646.     axp->flags.rejsent ? 'R' : ' ',
  647.     axp->flags.remotebusy ? 'B' : ' ');
  648.     tprintf(" %4d %4d",axp->vs,axp->vr);
  649.     tprintf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  650.     tprintf(" %02u/%02u",axp->retries,axp->n2);
  651.     tprintf(" %s\n",Ax25states[axp->state]);
  652.     tprintf("srtt = %lu mdev = %lu ",axp->srt,axp->mdev);
  653.     tprintf("T1: ");
  654.     if(run_timer(&axp->t1))
  655.         tprintf("%lu",read_timer(&axp->t1));
  656.     else
  657.         tprintf("stop");
  658.     tprintf("/%lu ms; ",dur_timer(&axp->t1));
  659.  
  660.     tprintf("T3: ");
  661.     if(run_timer(&axp->t3))
  662.         tprintf("%lu",read_timer(&axp->t3));
  663.     else
  664.         tprintf("stop");
  665.     tprintf("/%lu ms; ",dur_timer(&axp->t3));
  666.  
  667.     tprintf("T4: ");
  668.     if(run_timer(&axp->t4))
  669.     tprintf("%lu",(read_timer(&axp->t4)/1000L));
  670.     else
  671.         tprintf("stop");
  672.     tprintf("/%lu sec\n",(dur_timer(&axp->t4)/1000L));
  673. }
  674.  
  675. /* Set limit on retransmission backoff */
  676. static int
  677. doblimit(argc,argv,p)
  678. int argc;
  679. char *argv[];
  680. void *p;
  681. {
  682.     return setlong(&Blimit,"blimit",argc,argv);
  683. }
  684.  
  685. /* Display or change our AX.25 address */
  686. static int
  687. domycall(argc,argv,p)
  688. int argc;
  689. char *argv[];
  690. void *p;
  691. {
  692.     char tmp[AXBUF];
  693.  
  694.     if(argc < 2){
  695.         tprintf("%s\n",pax25(tmp,Mycall));
  696.         return 0;
  697.     }
  698.     if(setcall(Mycall,argv[1]) == -1)
  699.         return -1;
  700. #ifdef MAILBOX
  701.     setmbnrid();
  702. #endif
  703.     return 0;
  704. }
  705.  
  706. #ifdef TTYCALL
  707.  
  708. /* Display or change ttylink AX.25 address */
  709. static int
  710. dottycall(argc,argv,p)
  711. int argc;
  712. char *argv[];
  713. void *p;
  714. {
  715.     char tmp[AXBUF];
  716.  
  717.     if(argc < 2){
  718.         tprintf("%s\n",pax25(tmp,Ttycall));
  719.         return 0;
  720.     }
  721.     if(setcall(Ttycall,argv[1]) == -1)
  722.         return -1;
  723.     return 0;
  724. }
  725.  
  726. #endif
  727.  
  728. /* Control AX.25 digipeating */
  729. static int
  730. dodigipeat(argc,argv,p)
  731. int argc;
  732. char *argv[];
  733. void *p;
  734. {
  735.     return setflag(argc,argv[1],AX25_DIGI,argv[2]);
  736. }
  737.  
  738. static int
  739. doversion(argc,argv,p)
  740. int argc;
  741. char *argv[];
  742. void *p;
  743. {
  744.     return setshort(&Axversion,"AX25 version",argc,argv);
  745. }
  746.  
  747. static int
  748. doaxirtt(argc,argv,p)
  749. int argc;
  750. char *argv[];
  751. void *p;
  752. {
  753.     return setlong(&Axirtt,"Initial RTT (ms)",argc,argv);
  754. }
  755.  
  756. /* Set idle timer */
  757. static int
  758. dot3(argc,argv,p)
  759. int argc;
  760. char *argv[];
  761. void *p;
  762. {
  763.     return setlong(&T3init,"Idle poll timer (ms)",argc,argv);
  764. }
  765.  
  766. /* Set link redundancy timer */
  767. static int
  768. dot4(argc,argv,p)
  769. int argc;
  770. char *argv[];
  771. void *p;
  772. {
  773.     return setlong(&T4init,"Link redundancy timer (sec)",argc,argv);
  774. }
  775.  
  776.  
  777. /* Set retry limit count */
  778. static int
  779. don2(argc,argv,p)
  780. int argc;
  781. char *argv[];
  782. void *p;
  783. {
  784.     return setshort(&N2,"Retry limit",argc,argv);
  785. }
  786. /* Force a retransmission */
  787. static int
  788. doaxkick(argc,argv,p)
  789. int argc;
  790. char *argv[];
  791. void *p;
  792. {
  793.     struct ax25_cb *axp;
  794.  
  795.     axp = MK_FP(htoi(argv[1]),8);
  796.     if(!ax25val(axp)){
  797.         tprintf(Notval);
  798.         return 1;
  799.     }
  800.     kick_ax25(axp);
  801.     return 0;
  802. }
  803. /* Set maximum number of frames that will be allowed in flight */
  804. static int
  805. domaxframe(argc,argv,p)
  806. int argc;
  807. char *argv[];
  808. void *p;
  809. {
  810.     return setshort(&Maxframe,"Window size (frames)",argc,argv);
  811. }
  812.  
  813. /* Set maximum length of I-frame data field */
  814. static int
  815. dopaclen(argc,argv,p)
  816. int argc;
  817. char *argv[];
  818. void *p;
  819. {
  820.     return setshort(&Paclen,"Max frame length (bytes)",argc,argv);
  821. }
  822. /* Set size of I-frame above which polls will be sent after a timeout */
  823. static int
  824. dopthresh(argc,argv,p)
  825. int argc;
  826. char *argv[];
  827. void *p;
  828. {
  829.     return setshort(&Pthresh,"Poll threshold (bytes)",argc,argv);
  830. }
  831.  
  832. /* Set high water mark on receive queue that triggers RNR */
  833. static int
  834. doaxwindow(argc,argv,p)
  835. int argc;
  836. char *argv[];
  837. void *p;
  838. {
  839.     return setshort(&Axwindow,"AX25 receive window (bytes)",argc,argv);
  840. }
  841. /* End of ax25 subcommands */
  842.  
  843. /* Initiate interactive AX.25 connect to remote station */
  844. int
  845. doconnect(argc,argv,p)
  846. int argc;
  847. char *argv[];
  848. void *p;
  849. {
  850.     struct sockaddr_ax fsocket;
  851.     struct session *sp;
  852.     struct iface *ifp;
  853.     int ndigis,i;
  854.     char digis[MAXDIGIS][AXALEN];
  855.     char target[AXALEN];
  856.     int split = 0;
  857.  
  858.     /*Make sure this comes from console - WG7J*/
  859.     if(Curproc->input != Command->input)
  860.         return 0;
  861.  
  862. #ifdef ALLSERV
  863.     if(argv[0][0] == 's')   /* use split screen */
  864.     split  = 1;
  865. #endif
  866.  
  867.     if(((ifp = if_lookup(argv[1])) != NULLIF) && (ifp->type != CL_AX25)) {
  868.         tprintf("Iface %s not an AX25 type interface\n",argv[1]);
  869.         return 1;
  870.     }
  871.  
  872.     if(setcall(target,argv[2]) == -1){
  873.         tprintf("Bad callsign %s\n", argv[2]);
  874.         return 1;
  875.     }
  876.  
  877.     /* If digipeaters are given, put them in the routing table */
  878.     if(argc > 3){
  879.         if(setcall(target,argv[2]) == -1){
  880.             tprintf("Bad callsign %s\n", argv[2]);
  881.             return 1;
  882.         }
  883.         ndigis = argc - 3;
  884.         if(ndigis > MAXDIGIS){
  885.             tprintf("Too many digipeaters\n");
  886.             return 1;
  887.         }
  888.         for(i=0;i<ndigis;i++){
  889.             if(setcall(digis[i],argv[i+3]) == -1){
  890.                 tprintf("Bad digipeater %s\n",argv[i+3]);
  891.                 return 1;
  892.             }
  893.         }
  894.     if(ax_add(target,AX_AUTO,digis,ndigis,ifp) == NULLAXR){
  895.             tprintf("Route add failed\n");
  896.             return 1;
  897.         }
  898.     }
  899.     /* Allocate a session descriptor */
  900.     if((sp = newsession(argv[2],AX25TNC,split)) == NULLSESSION){
  901.     tputs(TooManySessions);
  902.         return 1;
  903.     }
  904.     if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
  905.     tputs(Nosock);
  906.         freesession(sp);
  907.         keywait(NULLCHAR,1);
  908.         return 1;
  909.     }
  910.     fsocket.sax_family = AF_AX25;
  911.     setcall(fsocket.ax25_addr,argv[2]);
  912.     strncpy(fsocket.iface,argv[1],ILEN);
  913.     return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_ax));
  914. }
  915.  
  916. /* Display and modify AX.25 routing table */
  917. static int
  918. doaxroute(argc,argv,p)
  919. int argc;
  920. char *argv[];
  921. void *p;
  922. {
  923.     char tmp[AXBUF];
  924.     int i,ndigis;
  925.     register struct ax_route *axr;
  926.     char target[AXALEN],digis[MAXDIGIS][AXALEN];
  927.     struct iface *iface;
  928.  
  929.     if(argc < 2){
  930.     tprintf("Target    Iface  Type  Mode Digipeaters\n");
  931.         for(axr = Ax_routes;axr != NULLAXR;axr = axr->next){
  932.         tprintf("%-10s%-7s%-6s",pax25(tmp,axr->target),
  933.          axr->iface->name,axr->type == AX_LOCAL ? "Local":"Auto");
  934.             switch(axr->mode){
  935.             case AX_VC_MODE:
  936.                 tprintf(" VC ");
  937.                 break;
  938.             case AX_DATMODE:
  939.                 tprintf(" DG ");
  940.                 break;
  941.             case AX_DEFMODE:
  942.                 tprintf(" IF ");
  943.                 break;
  944.             default:
  945.                 tprintf(" ?? ");
  946.                 break;
  947.             }
  948.  
  949.             for(i=0;i<axr->ndigis;i++){
  950.                 tprintf(" %s",pax25(tmp,axr->digis[i]));
  951.             }
  952.         if(tputc('\n') == EOF)
  953.                 return 0;
  954.         }
  955.         return 0;
  956.     }
  957.     if(argc < 4){
  958.     tprintf("Usage: ax25 route add <target> <iface> [digis...]\n");
  959.     tprintf("       ax25 route drop <target> <iface>\n");
  960.     tprintf("       ax25 route mode <target> <iface> [mode]\n");
  961.         return 1;
  962.     }
  963.     if(setcall(target,argv[2]) == -1){
  964.         tprintf("Bad target %s\n",argv[2]);
  965.         return 1;
  966.     }
  967.     if((iface = if_lookup(argv[3])) == NULLIF){
  968.     tprintf(Badinterface,argv[3]);
  969.     return 1;
  970.     }
  971.     switch(argv[1][0]){
  972.     case 'a':       /* Add route */
  973.     ndigis = argc - 4;
  974.         if(ndigis > MAXDIGIS){
  975.             tprintf("Too many digipeaters\n");
  976.             return 1;
  977.         }
  978.         for(i=0;i<ndigis;i++){
  979.         if(setcall(digis[i],argv[i+4]) == -1){
  980.         tprintf("Bad digipeater %s\n",argv[i+4]);
  981.                 return 1;
  982.             }
  983.         }
  984.     if(ax_add(target,AX_LOCAL,digis,ndigis,iface) == NULLAXR){
  985.             tprintf("Failed\n");
  986.             return 1;
  987.         }
  988.         break;
  989.     case 'd':       /* Drop route */
  990.     if(ax_drop(target,iface) == -1){
  991.             tprintf("Not in table\n");
  992.             return 1;
  993.         }
  994.         break;
  995.     case 'm':       /* Alter route mode */
  996.     if((axr = ax_lookup(target,iface)) == NULLAXR){
  997.             tprintf("Not in table\n");
  998.             return 1;
  999.         }
  1000.     switch(argv[4][0]){
  1001.         case 'i':       /* use default interface mode */
  1002.             axr->mode = AX_DEFMODE;
  1003.             break;
  1004.         case 'v':       /* use virtual circuit mode */
  1005.             axr->mode = AX_VC_MODE;
  1006.             break;
  1007.         case 'd':       /* use datagram mode */
  1008.             axr->mode = AX_DATMODE;
  1009.             break;
  1010.         default:
  1011.         tprintf("Unknown mode %s\n", argv[4]);
  1012.             return 1;
  1013.         }
  1014.         break;
  1015.     default:
  1016.         tprintf("Unknown command %s\n",argv[1]);
  1017.         return 1;
  1018.     }
  1019.     return 0;
  1020. }
  1021.  
  1022. /* ax25 timers type - linear v exponential */
  1023. static int
  1024. doaxtype(argc,argv,p)
  1025. int argc ;
  1026. char *argv[] ;
  1027. void *p ;
  1028. {
  1029.     extern int lapbtimertype;
  1030.  
  1031.     if (argc < 2) {
  1032.         tprintf("AX25 timer type is ");
  1033.         switch(lapbtimertype){
  1034.         case 2:
  1035.             tprintf("original\n");
  1036.             break;
  1037.         case 1:
  1038.             tprintf("linear\n");
  1039.             break;
  1040.         case 0:
  1041.             tprintf("exponential\n");
  1042.             break;
  1043.         }
  1044.         return 0 ;
  1045.     }
  1046.     
  1047.     switch (argv[1][0]) {
  1048.         case 'o':
  1049.         case 'O':
  1050.             lapbtimertype = 2 ;
  1051.             break ;
  1052.         case 'l':
  1053.         case 'L':
  1054.             lapbtimertype = 1 ;
  1055.             break ;
  1056.         case 'e':
  1057.         case 'E':
  1058.             lapbtimertype = 0 ;
  1059.             break ;
  1060.         default:
  1061.             tprintf("use: ax25 timertype [original|linear|exponential]\n") ;
  1062.             return -1 ;
  1063.     }
  1064.  
  1065.     return 0 ;
  1066. }
  1067.